//
//  MoStandardAlert.swift
//  dycommon_Example
//
//  Created by zhuxietong on 2021/2/9.
//  Copyright © 2021 CocoaPods. All rights reserved.
//

import Foundation
import Eelay
import RxSwift
import Foundation

public enum EditAction {
    case create(NSMutableDictionary)
    case update(NSMutableDictionary)
    case delete(NSMutableDictionary)
    public var object:NSMutableDictionary{
        switch self {
            case .create(let a),.update(let a),.delete(let a):return a
        }
      
    }
}


extension UICss{
    
}


@objc open class DialogContent:MoDisplayNode{
    public var success:(_:EditAction)->Void = {_ in}
    public var edit:(_:EditAction)->Void = {_ in}


    public let contentText = ASTextNode2()
    public var updatedSize:(_:CGSize)->Void = {_ in}
    public weak var alert:MoAlertController? = nil
    
    open func alertDone(index:Int,alert:MoAlertController){
        
    }
    
    open override func mo_model_reload() {
        let message_alignment = NSTextAlignment(rawValue: mo.model[int:"message_alignment",1]) ?? .center
        switch message_alignment {
        case .left:
            contentText.attributedText = mo.model["message",""].ui.left.lineSpace(5).font(font: MoAlertController.appearance.contentTextStyle.font).color(color: MoAlertController.appearance.contentTextStyle.color).astring
        case .right:
            contentText.attributedText = mo.model["message",""].ui.right.lineSpace(5).font(font: MoAlertController.appearance.contentTextStyle.font).color(color: MoAlertController.appearance.contentTextStyle.color).astring
        default:
            contentText.attributedText = mo.model["message",""].ui.center.lineSpace(5).font(font: MoAlertController.appearance.contentTextStyle.font).color(color: MoAlertController.appearance.contentTextStyle.color).astring
        }
    }
    public required init() {
        super.init()
    }
    open override func specGetter() -> _Spec {
        return _Spec.inset([], MoAlertController.appearance.contentTextStyle.padding, child: .stack(["v",&-.stretch], childs: [
            contentText.Spec,
        ]))
    }
    open override func layoutDidFinish() {
        updatedSize(bounds.size)
    }
    
}
public enum ButtonArrangement {
    case alert
    case sheet
}


open class DialogFooter:MoDisplayNode{
    public class appearance{
        public static var showSeparator = true
        public static var buttonHeight:CGFloat = 50
    }
    public var lineSeparators:[ASDisplayNode] = []
    public var topSeparator = ASDisplayNode()
    public var buttons = [ASButtonNode](){
        didSet{
            switch resultArrange {
            case .alert:
                lineSeparators = []
                for _ in 0..<buttons.count{
                    let line = ASDisplayNode()
                    line.backgroundColor = ._separator
                    topSeparator.backgroundColor = ._separator
                    lineSeparators.append(line)
                }
              
                if alertCss.space < 1 && alertCss.padding.bottom < 1{
                    for bt in buttons {
                        bt.ui.set(radius: 0, width: nil, color: nil)
                    }
                }
            default:
                break
            }
        }
    }
    
    public var updatedSize:(_:CGSize)->Void = {_ in}
    public var arrange:ButtonArrangement = .alert
    
    public var alertCss:[UICss] = [.padding(.zero),.space(0)]
    public var sheetCss:[UICss] = [.padding([16]),.space(16)]
    public var width:CGFloat = Swidth
    
    var blank = ASDisplayNode()
    
    open override func addLayoutRules() {
        super.addLayoutRules()
       
    }
    public var resultArrange:ButtonArrangement{
        var arrange = self.arrange
        if buttons.count > 2{
            arrange = .sheet
        }
        return arrange
    }

    open override func specGetter() -> _Spec {
        if buttons.count < 1{
            return blank["0.2"]
        }
        var css = alertCss
        switch resultArrange {
        case .alert:
            css = alertCss
            let count = buttons.count
            let w = (width - CGFloat(count) * alertCss.space)/CGFloat(count)
            let bts = buttons.map { (b) -> _Spec in
                return b["\(appearance.buttonHeight)",w]
            }
            
            if appearance.showSeparator{
                var newBts = [_Spec]()
                for (i,spec) in bts.enumerated() {
                    newBts.append(spec)
                    let line = lineSeparators[i]
                    newBts.append(line[TP.separatorHeight,"\(appearance.buttonHeight)"])
                }
                newBts.removeLast()
                return _Spec.inset([], .zero, child: .stack(["v",&-.stretch], childs: [
                    topSeparator["\(TP.separatorHeight)"],
                    .stack(["h",&-.stretch,_nowrap], childs: newBts)
                ]))
            }else{
               
                return _Spec.inset([], css.padding, child: .stack(["h|\(css.space)",&-.stretch,_nowrap], childs: bts))
            }
            
          
        default:
            css = sheetCss

            let count = buttons.count
            _ = (width - CGFloat(count) * alertCss.space)/CGFloat(count)
            let bts = buttons.map { (b) -> _Spec in
                return b["\(appearance.buttonHeight)"]
            }
            
            return _Spec.inset([], css.padding, child: .stack(["v|\(css.space)",&-.stretch], childs: bts))
        }
    }
    
    open override func layoutDidFinish() {
        updatedSize(bounds.size)
    }
}
open class MoCustomDialog:MoDialog<DialogContent>{
    public class Body:DialogContent{
        
    }
    
}




open class MoDialog<ContentNode:DialogContent>: MoAlertController {
//    public typealias Content = ContentNode
    public var footerStyle:[UICss] = []
    public var contentStyle:[UICss] = []
    public var headerStyle:[UICss] = []
    public var modalStyle:[UICss] = []
    public var arrange:ButtonArrangement = .alert
    
    open func success(success:@escaping (_:EditAction)->Void)->Self{
        node.success = success
        return self
    }

    open override func defaultStyle() -> [UICss] {
        return [.size(CGSize(width: Swidth-60, height: Swidth-60))]
    }
    
    
    public enum ActionStyle {
        case confirm
        case cancel
        case `default`
        public func button(name:String,alert:MoAlertController,action:@escaping(_:MoAlertController?)->Void)->ASButtonNode{
            switch self {
            case .cancel:
                let bt = appearance.cancelButton()
                bt.ui.ntitle(title: name).touchUpInside { (bt) in
                    action(alert)
                }
                return bt
            case .confirm:
                let bt = appearance.confirmButton()
                bt.ui.ntitle(title: name).touchUpInside { (bt) in
                    action(alert)
                }
                return bt
            default:
                let bt = appearance.defaultButton()
                bt.ui.ntitle(title: name).touchUpInside { (bt) in
                    action(alert)
                }
                return bt
            }
        }
    }
    
    
    public func arrange(_ arrange:ButtonArrangement)->MoDialog{
        self.arrange = arrange
        return self
    }
    public var alert:Self{
        arrange = .alert
        type = .alert
        return self
    }
    public var sheet:Self{
        arrange = .sheet
        type = .sheet
        return self
    }
    
    public var obj:NSMutableDictionary = NSMutableDictionary()
    
    open func title(_ title:String) -> MoDialog {
        obj["title"] = title
        return self
    }
    
    open func message(_ msg:String) -> MoDialog {
        obj["message"] = msg
        return self
    }
    open func message(alignment:NSTextAlignment) -> MoDialog {
        obj["message_alignment"] = alignment.rawValue
        return self
    }
    
    open var canle:MoDialog{
        obj["cancel"] = "取消".loc
        return self
    }
    
    @discardableResult
    open func append(name:String,action:@escaping(_:MoAlertController?)->Void,style:ActionStyle = .default) -> MoDialog {
        actions.append((name,action,style))
        return self
    }
    
    public var actions:[(String,(_:MoAlertController?)->Void,ActionStyle)] = []
    
    public var bts:[ASButtonNode] = []
    public var titleN = ASTextNode2()
    
    public func model(_ model:NSMutableDictionary)->MoDialog{
        mo.model = model
//        node.mo.model = model
        return self
    }
    
//    let bridge = ASBridge()
    public var node:DialogContent = ContentNode()
    public var footer = DialogFooter()
    public var footerBridge = ASBridge()
    
    
    
    public var heightConstraint = NSLayoutConstraint()
    open override func layModal(modalView:UIView){
        
        switch type {
        case .alert:
            if let h = keyboadAvoidBack.setEeLays(lays: [
                [touchBackground,[ee.T.L.B.R]],
                [modalView,style.size.width,[ee.X],[ee.Y,style.offsetY],"\(style.size.height)"]
            ]).1.last{
                heightConstraint = h
            }
        default:
            if let h = keyboadAvoidBack.setEeLays(lays: [
                [touchBackground,[ee.T.L.B.R]],
                [modalView,[ee.L.B.R],"\(style.size.height)"]
            ]).1.last{
                heightConstraint = h
            }
        }
       
    }
    
    open func updateModalHeight()  {
        if contentHeight > 0 && footerHeight > 0{
//            print("+0000--\(contentHeight)--\(footerHeight)--\(titleLabel.frame)")
            let y = titleLabel.frame.origin.y + titleLabel.frame.size.height
            
            var modalHeight = y  + 5 + contentHeight + footerHeight
            let limitHeight = Sheight - MoUIAdapter.safeInset.top - MoUIAdapter.safeInset.top - style.offsetY - 60
            if type == .sheet{
                 modalHeight = modalHeight + MoUIAdapter.safeInset.bottom
            }
            if modalHeight > limitHeight{
                modalHeight = limitHeight
                tableView.isScrollEnabled = true
            }else{
                tableView.isScrollEnabled = false
            }
            heightConstraint.constant = modalHeight

            tableNode.performBatch(animated: false) {
                
            } completion: { _ in
                
            }
//            heightConstraint.constant = modalHeight

            modalView.setNeedsLayout()
            modalView.layoutIfNeeded()
                        
            
        }
    }
    public var contentHeight:CGFloat = 0{
        didSet{
            updateModalHeight()
        }
    }
    public var footerHeight:CGFloat = 0{
        didSet{
            updateModalHeight()
        }
    }
    
    public var footerBri = ASBridge()
    open override func layoutCloseBt() {
        jo_contentView.eelay = [
            [closeBt,[titleLabel,ee.Y],[ee.R,-12],"26",26],
        ]
        
    }
    open override func layTable(tableView: UIView) {
        
        jo_contentView.setEeLays(lays: [
            [titleLabel,[ee.T.L.R,[titleTextStyle.padding.top,titleTextStyle.padding.left,-titleTextStyle.padding.right]]],
            [tableView,[ee.L.R],[titleLabel,ee.B,ee.T,5],[footerBri,ee.T,ee.B,0]],
            [footerBri,[ee.L.R],[ee.B.safe]],
        ])
//        titleLabel.setco

        node.clipsToBounds = false
        node.updatedSize = {
            [weak self] size in
            guard let `self` = self else {
                return
            }
            self.contentHeight = size.height
        }
        footerBri.updateSize = {
            [weak self] size in
            guard let `self` = self else {
                return
            }
            self.footerHeight = size.height
        }
        
        footer.arrange = arrange
        footerBri.node = footer

//        titleLabel.ui.font(font: appearance.titleTextStyle.font).text(color:appearance.titleTextStyle.color).center.text("提示")
//        node.contentText.attributedText = "".ui.center.font(font: appearance.contentTextStyle.font).color(color: appearance.contentTextStyle.color).lineSpace(5).center.astring
        node.alert = self
    }
    
    
    open override func viewDidLoad() {
        enabelBackTouch = false
        style.append(.backgroundColor(._background))
//        style.update(.cornerRadius(6))
        style.update(.size([(Swidth-60.co),480]))
        super.viewDidLoad()
        titleLabel.ui.font(font: appearance.titleTextStyle.font).center.color(color: appearance.titleTextStyle.color)
        titleLabel.text = obj["title",""]
//        messageN.attributedText = obj["message",""].ui.font14.color(color: ._foreground).alignment(align: .center).lineSpace(6).astring
        let cancel = mo.model["cancel",""]
        if cancel.len > 0{
            append(name: cancel, action: {_ in 
            }, style: .cancel)
        }
        
        bts.removeAll()
        for (i,action) in actions.enumerated() {
//            print("-dd---KK",action.2)
            let bt = action.2.button(name: action.0,alert: self, action: action.1)
            bt.actionID = "\(i)"
//            bt.actionID = ""
            bts.append(bt)
        }
        
        for bt in bts {
            bt.addTarget(self, action: #selector(buttonAction(sender:)), forControlEvents: .touchUpInside)
        }
        node.alert = self
        if mo.model.allKeys.count < 1{
            node.mo.model = obj
        }else{
            node.mo.model = mo.model
        }
        
        footer.width = self.style.width
        footer.arrange = arrange
        footer.buttons = bts
        footer.setNeedsLayout()
        footer.layoutIfNeeded()
    }
    
    @objc func buttonAction(sender:ASButtonNode){
        let n = sender.actionID.IntValue
        node.alertDone(index: n, alert: self)
    }
  

    open override func specGetter() -> _Spec {
        return .inset([], .zero, child: _Spec.stack(["v",&-.stretch], childs: [
            node.Spec,
        ]))
    }
}
